var sw=15,//一个方块的宽度
	sh=15,//一个方块的高度
	tr=40,//行数
	td=40;//列数

var snake=null,//蛇的实例
	food=null,  //食物的实例
	game=null  //游戏的实例
	;
/* 方块构造函数 */
function Square(x,y,classname){
	//0 0    0,0
	//15,0   1,0		
	//30,0   2,0
	
	this.x=x*sw;
	this.y=y*sh;
	this.class=classname;
	
	this.viewContent=document.createElement('div');//方块对应的DOM元素
	this.viewContent.className=this.class;
	this.parent=document.getElementById('snakewarp');//方块的父级
}
/* 为对象构造器添加新方法：原型方法，往构造器里面塞,这是共享的方法 */
Square.prototype.create=function(){//创建方块的DOM,并添加到页面里
	this.viewContent.style.position='absolute';
	this.viewContent.style.width=sw+'px';
	this.viewContent.style.height=sh+'px';
	this.viewContent.style.left=this.x+'px';
	this.viewContent.style.top=this.y+'px';
	
	this.parent.appendChild(this.viewContent);
};
Square.prototype.remove=function(){//删了DOM元素
	this.parent.removeChild(this.viewContent);
};
/* 蛇 */
function Snake(){
	this.head=null;//存一下蛇头的信息
	this.tail=null;//存一下蛇尾的信息
	this.pos=[];//存储蛇身上的每一个小方块的位置信息
	
	this.directionNum={//存储蛇走的方向，用一个对象表示
		left:{
			x:-1,
			y:0,
			rotate:100 //蛇头在不同的方向中应该旋转，不然始终是向右
		},
		right:{
			x:1,
			y:0
		},
		up:{
			x:0,
			y:-1,
			rotate:-90
		},
		down:{
			x:0,
			y:1,
			rotate:90
		}
	}
}
Snake.prototype.init=function(){
	//创建蛇头
	var snakeHead=new Square(2,0,'snakeHead');
	snakeHead.create();
	this.head=snakeHead; //存储蛇头信息
	this.pos.push([2,0]); //把蛇头的位置存起来
	
	//创建蛇身体1
	var snakeBody1=new Square(1,0,'snakeBody');//先给属性值
	snakeBody1.create();//再调方法
	this.pos.push([1,0]);//把蛇的第一节坐标压进数组
	//创建蛇身体2
	var snakeBody2=new Square(0,0,'snakeBody');//先给属性值
	snakeBody2.create();//再调方法
	this.tail=snakeBody2;//存储蛇尾信息
	this.pos.push([0,0]);//把蛇的第一节坐标压进数组
	
	//形成链表关系
	snakeHead.last=null;
	snakeHead.next=snakeBody1;
	snakeBody1.last=snakeHead;
	snakeBody1.next=snakeBody2;
	snakeBody2.last=snakeBody1;
	snakeBody2.next=null;
	
	//添加一条属性，用来表示蛇走的方向
	this.direction=this.directionNum.right;//默认让蛇往右走
}
//这个方法用来获取蛇头的下一个位置对应的元素，要根据元素做不同的事情
Snake.prototype.getNextPos=function(){
	var nextPos=[//蛇头要走的下一个点的坐标
		this.head.x/sw+this.direction.x,
		this.head.y/sh+this.direction.y
	]
	
	//下一个点是自己，代表游戏结束
	var selfCollied=false;//代表是否撞到自己
	
	this.pos.forEach(function(value){
		if(value[0]==nextPos[0] && value[1]==nextPos[1]){
			//如果数组中的两个数据都相等，代表撞到自己了
			selfCollied=true;
		}
	});
	if(selfCollied){
		console.log("撞到自己");
		this.strategies.die().call(this);
		return;
	}
	
	//下一个点是围墙，代表游戏结束
	if(nextPos[0]<0 || nextPos[1]<0 || nextPos[0]>td-1 || nextPos[1]>tr-1){
		console.log("撞墙了");
		this.strategies.die().call(this);
		return;
	}
	//下一个点是食物，代表吃
	if(food && food.pos[0]==nextPos[0] && food.pos[1]==nextPos[1]){
		console.log("吃到食物");
		this.strategies.eat.call(this);
		return;
	}
	
	// this.strategies.eat();
	//下一个点空白，走
	this.strategies.move.call(this);//把this指向的实例传进来
};
//处理碰撞后要做的事儿
Snake.prototype.strategies={
	move:function(format){//这个参数用于决定要不要删除最后一个方块
		console.log("move方法调用");
		//创建一个新的身体(在旧蛇头的位置)
		var newBody=new Square(this.head.x/sw,this.head.y/sh,'snakeBody');
		//更新链表的关系
		newBody.next=this.head.next;
		newBody.next.last=newBody;
		newBody.last=null;
		this.head.remove();//把旧蛇头从原来的位置删除
		newBody.create();//创建
		
		//创建一个新的蛇头(下一个要走的点)
		var newHead=new Square(this.head.x/sw+this.direction.x,this.head.y/sh+this.direction.y,'snakeHead')
		//更新链表的关系
		newHead.next=newBody;
		newHead.last=null;
		newBody.last=newHead;
		newHead.viewContent.style.transform='rotate('+this.direction.rotate+'deg)';
		newHead.create();
		//更新方块坐标
		this.pos.splice(0,0,[this.head.x/sw+this.direction.x,this.head.y/sh+this.direction.y]);
		this.head=newHead;
		
		//根据不同情况是否删除尾巴
		if(!format){//false，删除
			this.tail.remove();
			this.tail=this.tail.last;//null
			this.pos.pop();
		}
	},
	eat:function(){
		console.log("eat方法调用");
		this.strategies.move.call(this,true);
		createFood();
		game.score++;
	},
	die:function(){
		console.log("die方法调用");
		game.over();
	}
}
snake=new Snake();
// snake.init();
// snake.getNextPos();

//创建食物
function createFood(){
	//食物小方块的随机坐标
	var x=null;
	var y=null;
	var include=true; //循环跳出的条件，true表示食物的坐标在蛇身上(需要继续循环)，false表示食物的坐标不在蛇身上
	while(include){
		x=Math.round(Math.random()*(td-1));
		y=Math.round(Math.random()*(tr-1));
		snake.pos.forEach(function(value){
			if(x!=value[0] && y!=value[1]){
				//这个条件成立说明现在随机出来的这个坐标，在蛇身上没有找到
				include=false;
			}
		});
	}
	//生成食物
	food=new Square(x,y,'food');
	food.pos=[x,y];//存储以下食物的坐标，用于跟蛇头要走的下一个点做对比
	var foodDom=document.querySelector('.food');
	if(foodDom){
		foodDom.style.left=x*sw+'px';
		foodDom.style.top=y*sh+'px';
	}else{
		food.create();
	}
}


//创建游戏逻辑
function Game(){
	this.timer=null;
	this.score=0;
}
Game.prototype.init=function(){
	snake.init();
	createFood();
	
	document.onkeydown=function(ev){
		if(ev.which==37 && snake.direction!=snake.directionNum.right){//往右走的时候不能按左键
			snake.direction=snake.directionNum.left;
		}else if(ev.which==38 && snake.direction!=snake.directionNum.down){
			snake.direction=snake.directionNum.up;
		}else if(ev.which==39 && snake.direction!=snake.directionNum.left){
			snake.direction=snake.directionNum.right;
		}else if(ev.which==40 && snake.direction!=snake.directionNum.up){
			snake.direction=snake.directionNum.down;
		}
	}
	this.start();
}
Game.prototype.start=function(){//开始游戏
	this.timer=setInterval(function(){
		snake.getNextPos();
	},200);
}
Game.prototype.pause=function(){//暂停
	clearInterval(this.timer);
}
Game.prototype.over=function(){
	clearInterval(this.timer);
	alert("你的得分为："+this.score);
	//游戏回到最初始状态
	var snakewarp=document.getElementById('snakewarp');
	snakewarp.innerHTML='';
	snake=new Snake();
	game=new Game();
	var startBtnWarp=document.querySelector('.startBtn');
	startBtnWarp.style.display='block';
}
//开始游戏
game=new Game();
var startBtn=document.querySelector('.startBtn button');
startBtn.onclick=function(){
	startBtn.parentNode.style.display='none';
	game.init();
}
//暂停
var snakewarp=document.getElementById('snakewarp');
var pauseBtn=document.querySelector('.pauseBtn button');
snakewarp.onclick=function(){//暂停
	game.pause();
	pauseBtn.parentNode.style.display='block';
}
pauseBtn.onclick=function(){//继续
	game.start();
	pauseBtn.parentNode.style.display='none';
}